/*
 * process.c
 *
 *  Created on: 2011/04/23
 *      Author: AKS
 */

#include "core/include/list.h"
#include "core/include/types.h"
#include "core/include/aks_processor.h"
#include "core/include/process.h"

static WORD nextProcessID;
//static LIST_ITEM *executingProcess;

LIST_ITEM *waitingProcess;
LIST_ITEM *execReadyProcess;
LIST_ITEM *executingProcess;
LIST_ITEM *cycleProcess;

void initProcessController(void)
{
	waitingProcess   = NULL;
	execReadyProcess = NULL;
	executingProcess = NULL;
	cycleProcess     = NULL;

	nextProcessID = 1;

	return;
}


BOOL sleepCurrentProcess(WAKE_UP_CONDITION wakeCondition, void *wakeUpParamater)
{
	if( executingProcess != NULL)
	{
		((PROCESS*)executingProcess->load)->wakeUp      = wakeCondition;
		((PROCESS*)executingProcess->load)->wakeUpParam = wakeUpParamater;

        if(NULL != pushToList(&waitingProcess, executingProcess))
        {
            executingProcess = NULL;
        }

        return TRUE;
	}
	else
	{
		return FALSE;
	}
}


BOOL entryNewProcess(LIST_ITEM *process)
{
	if(NULL == pushToList(&waitingProcess, process))
	{
        return FALSE;
	}
	else
	{
        return TRUE;
	}
}


BOOL wakeUpNextProcess(void)
{
	if(execReadyProcess == NULL && executingProcess == NULL)
	{
		return FALSE;
	}
	else
	{
		// the case that no process is executing
		if(executingProcess == NULL)
		{
			executingProcess = popFromList(&execReadyProcess);
		}
		// the case that some process is executing
		else
		{
			// dispatch process 1: pending current process
			execReadyProcess = pushToList(&execReadyProcess, executingProcess);
			// dispatch process 2: load new process
			executingProcess = popFromList(&execReadyProcess);
		}

		return TRUE;
	}

	return FALSE;
}


WORD checkWakeUp(void)
{
	LIST_ITEM *ptr = waitingProcess;

	while(ptr != NULL)
	{
		if( TRUE == ((PROCESS *)ptr->load)->wakeUp( ((PROCESS *)ptr->load)->wakeUpParam ) )
		{
			LIST_ITEM *p = deleteFromList(&waitingProcess, ptr);
			pushToList(&execReadyProcess, p);
		}

		ptr = ptr->next;
	}

	return lengthOf(&execReadyProcess) + lengthOf(&executingProcess);
}
